home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 424_01 / ed_157 / match_search.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-11  |  20.0 KB  |  670 lines

  1. /*
  2.  * Copyright (C) 1992 by Rush Record (rhr@clio.rice.edu)
  3.  * 
  4.  * This file is part of ED.
  5.  * 
  6.  * ED is free software; you can redistribute it and/or modify it under the terms
  7.  * of the GNU General Public License as published by the Free Software Foundation.
  8.  * 
  9.  * ED is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  10.  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  11.  * PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  12.  * 
  13.  * You should have received a copy of the GNU General Public License along with ED
  14.  * (see the file COPYING).  If not, write to the Free Software Foundation, 675
  15.  * Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17. #include "opsys.h"
  18.  
  19. #include <stdio.h>
  20. #include <string.h>
  21.  
  22. #include "memory.h"
  23. #include "ctyp_dec.h"
  24. #include "rec.h"
  25. #include "window.h"
  26. #include "ed_dec.h"
  27. #include "buffer.h"
  28. #include "buf_dec.h"
  29. #include "cmd_enum.h"
  30. #include "regex.h"
  31.  
  32. #include "handy.h"
  33.  
  34. #define MAX_REGEX 64    /* maximum number of regexps that may be extracted from user's search string */
  35.  
  36. static Uchar normal[256] =
  37. {
  38.     0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
  39.     0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
  40.     0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
  41.     0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
  42.     0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
  43.     0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,
  44.     0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f,
  45.     0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,
  46.     0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
  47.     0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
  48.     0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
  49.     0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
  50.     0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
  51.     0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
  52.     0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
  53.     0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
  54. };
  55.  
  56. static Uchar table[257];    /* this is for user-specified search tables */
  57. static Char general,beginning,wild,tabledriven,regexp,wordmode;
  58. static Uchar *tbl1,*tbl2;
  59. static struct re_pattern_buffer pbuf,wbuf[MAX_REGEX];
  60. static Char startrec,startrecs[MAX_REGEX],endrec,endrecs[MAX_REGEX],must_recompile_regex;
  61. static Char *delim = NULL;    /* word-delimiter table */
  62. static Int nwords = 0;
  63.  
  64. extern Char *wordtable();
  65.  
  66. /******************************************************************************\
  67. |Routine: match_init
  68. |Callby: edit find_string word_fill
  69. |Purpose: Initializes local variables for match_search.
  70. |Arguments:
  71. |    flags is the set of flags that constrain the search. They are:
  72. |            [0] = g means case-insensitive, else (e) case-sensitive.
  73. |            [1] = b means match position is at beginning of string, else (e) end.
  74. |            [2] = w means WILDCARD is wildcard, else (n) not.
  75. |            [3] = n means no search table, else (t) table in effect.
  76. |            [4] = r means use regular expression searching, n means don't. Overrides the rest of the flags, except beginning/end.
  77. |            [5] = c means search-by-character (the default), else (w) search-by-word.
  78. \******************************************************************************/
  79. void match_init(flags)
  80. Char flags[6];
  81. {
  82.     general = flags[((int)SMODE_GENERAL) >> 1];
  83.     beginning = flags[((int)SMODE_BEGINNING) >> 1];
  84.     wild = flags[((int)SMODE_WILDCARDS) >> 1];
  85.     tabledriven = flags[((int)SMODE_TABLE_DRIVEN) >> 1];
  86.     if((regexp = flags[((int)SMODE_REGEXP) >> 1]) == 'r')
  87.         must_recompile_regex = 1;
  88.     wordmode = (flags[((int)SMODE_CHAR) >> 1] == 'w');
  89.     tbl1 = (tabledriven == 't')? normal : (general == 'g')? _my_toupper_ : normal;
  90.     tbl2 = (tabledriven == 't')? table : (general == 'g')? _my_toupper_ : normal;
  91.     delim = wordtable();
  92. }
  93.  
  94. /******************************************************************************\
  95. |Routine: parse_regex
  96. |Callby: match_search
  97. |Purpose: Preprocesses regexps so they work right, and compiles them.
  98. |Arguments:
  99. |    currec is the record being compared to the search string.
  100. |    curbyt is the position in the record where the comparison starts.
  101. |    searchbuf is the buffer containing the search string.
  102. \******************************************************************************/
  103. void parse_regexp(pbuf,buf,startrec,endrec)
  104. struct re_pattern_buffer *pbuf;
  105. Char *buf;
  106. Char *startrec,*endrec;
  107. {
  108.     Int i;
  109.     Char *p;
  110.     
  111.     if(buf[0] == '^')    /* check for ^... */
  112.     {
  113.         *startrec = 1;
  114.         i = strlen(buf) - 1;
  115.         if(i > 0 && buf[1] == '^')    /* change ^^... to \^... */
  116.             buf[0] = '\\';
  117.         else
  118.         {
  119.             for(p = buf;i--;p++)    /* slide exp to left */
  120.                 *p = *(p + 1);
  121.             *p = '\0';
  122.         }
  123.     }
  124.     else
  125.         *startrec = 0;
  126.     i = strlen(buf) - 1;
  127.     if(buf[i] == '$')    /* check for ...$ */
  128.     {
  129.         *endrec = 1;
  130.         if(i > 1 && buf[i - 1] == '$')    /* change ...$$ to ...\$ */
  131.             buf[i - 1] = '\\';
  132.         else
  133.             buf[i] = '\0';    /* shorten exp */
  134.     }
  135.     else
  136.         *endrec = 0;
  137.     re_compile_pattern(buf,strlen(buf),pbuf);    /* let the re_match call report an erroneous RE */
  138. }
  139.  
  140. /******************************************************************************\
  141. |Routine: match_search
  142. |Callby: edit find_string inquire word_fill
  143. |Purpose: Determines whether the current position is on a matching string.
  144. |         Returns the length of the matching string.
  145. |Arguments:
  146. |    currec is the record being compared to the search string.
  147. |    curbyt is the position in the record where the comparison starts.
  148. |    searchbuf is the buffer containing the search string.
  149. \******************************************************************************/
  150. Int match_search(currec,curbyt,searchbuf)
  151. rec_ptr currec;
  152. Int curbyt;
  153. buf_ptr searchbuf;
  154. {
  155.     register Uchar *cr,*cs,*t1,*t2,*p,*q;
  156.     register Int c1,c2;
  157.     rec_ptr r,s,tr,ts;
  158.     Int lr,ls,ss;
  159.     Int offset;
  160.     Char rbuf[1100],*pp,*qq;
  161.     Int i,j;
  162.     Char buf[1024];
  163.     
  164.     if((s = searchbuf->first) == (rec_ptr)&searchbuf->first)
  165.         return(0);
  166.     if(wordmode && searchbuf->nrecs > 1)
  167.         return(0);
  168.     if(must_recompile_regex)
  169.     {
  170.         must_recompile_regex = 0;
  171.         if(wordmode)
  172.         {
  173.             ts = s;
  174.             ss = 0;
  175.             nwords = 0;
  176.             strcpy(buf,s->data);
  177.             strcat(buf," ");
  178.             for(pp = buf;(qq = strchr(pp,' '));pp = ++qq)
  179.             {
  180.                 memcpy(rbuf,pp,(i = qq - pp));
  181.                 rbuf[i] = '\0';
  182.                 parse_regexp(wbuf + nwords,rbuf,startrecs + nwords,endrecs + nwords);
  183.                 if(++nwords > 64)
  184.                     break;
  185.             }
  186.         }
  187.         else
  188.         {
  189.             strcpy(buf,searchbuf->first->data);
  190.             parse_regexp(&pbuf,buf,&startrec,&endrec);
  191.         }
  192.     }
  193.     r = currec;
  194.     cr = (Uchar *)&r->data[curbyt];
  195.     offset = 0;
  196.     t1 = tbl1;
  197.     t2 = tbl2;
  198.     if(beginning == 'b')
  199.     {
  200.         lr = r->length - curbyt;
  201.         if(WINDOW[CURWINDOW].binary)    /* binary-mode search ignores linebreaks, has special handling for <0d> in search buffer */
  202.         {
  203.             if(curbyt == r->length)    /* disallow matches at eol in begin mode */
  204.                 return(0);
  205.             cs = (Uchar *)s->data;    /* start at beginning of search buffer's first record */
  206.             ls = s->length;
  207.             while(1)
  208.             {
  209.                 if(r == BASE)    /* hit end of file */
  210.                     return(0);
  211. /* insure we have another search buffer byte */
  212.                 while(!ls)    /* this record in search buffer ends, advance */
  213.                 {
  214.                     if((s = s->next) == (rec_ptr)&searchbuf->first)    /* end of search buffer, succeed */
  215.                         return(1);
  216.                     while(!lr)    /* insure another file byte is available */
  217.                     {
  218.                         if((r = r->next) == BASE)
  219.                             return(0);
  220.                         lr = r->length;
  221.                         cr = (Uchar *)r->data;
  222.                     }
  223.                     if(*(t2 + *cr++) != 13)    /* require a CR to match the search buffer linebreak */
  224.                         return(0);
  225.                     lr--;
  226.                     offset++;    /* advance for CR */
  227.                     cs = (Uchar *)s->data;    /* new pointers */
  228.                     ls = s->length;
  229.                 }
  230. /* insure we have another file byte */
  231.                 while(!lr)    /* ran out on file record, advance */
  232.                 {
  233.                     if((r = r->next) == BASE)
  234.                         return(0);
  235.                     lr = r->length;
  236.                     cr = (Uchar *)r->data;
  237.                 }
  238.                 if(wild == 'n')
  239.                 {
  240.                     if(*(t1 + *cs++) != *(t2 + *cr++))    /* compare */
  241.                         return(0);
  242.                 }
  243.                 else
  244.                 {
  245.                     if(*cs == WILDCARD)    /* wildcards match anything */
  246.                     {
  247.                         cs++;
  248.                         cr++;
  249.                     }
  250.                     else
  251.                         if(*(t1 + *cs++) != *(t2 + *cr++))    /* compare */
  252.                             return(0);
  253.                 }
  254.                 ls--;
  255.                 lr--;
  256.                 offset++;    /* advance offset */
  257.             }
  258.         }
  259.         if(regexp == 'r' && !wordmode)
  260.         {
  261.             if(startrec && curbyt)    /* ignore attempts not at beginning of record when ^... present */
  262.                 return(0);
  263.             if((i = re_match(&pbuf,(const char *)cr,lr,0,NULL)) == -2)
  264.                 goto regex_error;
  265.             if(i < 0)
  266.                 return(0);
  267.             if(endrec && (curbyt + i != r->length))    /* require match at end of record when ...$ present */
  268.                 return(0);
  269.             return(i);    /* note that re_match may return 0 as a success code. hmmm. */
  270.         }
  271.         if(wild == 'n' || regexp == 'r')    /* no wild cards, or wordmode regex processing */
  272.         {
  273. /*
  274. word mode (beginning):
  275.  
  276. 0) find a word in s, else succeed.
  277. 1) find a word in r, else fail.
  278. 2) if words don't compare equal, fail.
  279. 6) go to 2)
  280. */
  281.             if(wordmode)
  282.             {
  283.                 if(r == BASE)
  284.                     return(0);
  285.                 if(regexp != 'r')
  286.                 {
  287.                     for(cs = (Uchar *)s->data,ls = s->length;ls--;cs++)
  288.                         if(!delim[*cs])
  289.                             break;
  290.                     if(!ls)
  291.                         return(0);    /* search string contains only delims, or is empty */
  292.                 }
  293.                 if(!on_a_word(r,curbyt))    /* we can only succeed when on a word */
  294.                     return(0);
  295.                 ss = 0;    /* this is the current offset in the search string */
  296.                 tr = r;    /* this is a temporary rec_ptr for traversing the file */
  297.                 ts = s;    /* this is a temporary rec_ptr for traversing the search string */
  298.                 if(regexp == 'r')
  299.                 {
  300.                     if(!nwords)
  301.                         return(0);
  302.                     for(j = 0;j < nwords;j++)
  303.                     {
  304.                         if(startrecs[j] && curbyt)    /* ignore attempts not at beginning of record when ^... present */
  305.                             return(0);
  306.                         if(!get_word_start(BASE,&tr,&curbyt,&lr,&offset))
  307.                             return(0);
  308.                         if((i = re_match(wbuf + j,(const char *)tr->data + curbyt,lr,0,NULL)) == -2)
  309.                             goto regex_error;
  310.                         if(i < 0)
  311.                             return(0);
  312.                         if(endrecs[j] && (curbyt + i != r->length))    /* require match at end of record when ...$ present */
  313.                             return(0);
  314.                         curbyt += lr;    /* advance to past end of word in file */
  315.                     }
  316.                 }
  317.                 else
  318.                 {
  319.                     while(1)
  320.                     {
  321.                         if(!get_word_start(s,&ts,&ss,&ls,NULL))
  322.                             break;    /* we have a hit */
  323.                         if(!get_word_start(BASE,&tr,&curbyt,&lr,&offset))
  324.                             return(0);
  325.                         if(ls != lr)    /* word length mismatch */
  326.                             return(0);
  327.                         for(p = (Uchar *)ts->data + ss,q = (Uchar *)tr->data + curbyt,i = ls;i--;p++,q++)    /* compare the two words */
  328.                             if(*(t1 + *p) != *(t2 + *q))
  329.                                 return(0);
  330.                         curbyt += lr;    /* advance to past end of word in file */
  331.                         ss += ls;    /* advance to past end of word in search string */
  332.                     }
  333.                 }
  334.             }
  335.             else    /* not wordmode */
  336.                 do
  337.                 {
  338.                     if(r == BASE)
  339.                         return(0);
  340.                     if((ls = s->length) > lr)
  341.                         return(0);
  342.                     for(cs = (Uchar *)s->data;ls--;)
  343.                     {
  344.                         if(*(t1 + *cs++) != *(t2 + *cr++))
  345.                             return(0);
  346.                         offset++;
  347.                     }
  348.                     if((s = s->next) != (rec_ptr)&searchbuf->first) /* insure the file record ends here too */
  349.                     {
  350.                         if(cr != (Uchar *)&r->data[r->length])    /* search record ends, file record continues */
  351.                             return(0);
  352.                         r = r->next;
  353.                         lr = r->length;
  354.                         cr = (Uchar *)r->data;
  355.                         offset++;
  356.                     }
  357.                 } while(s != (rec_ptr)&searchbuf->first);
  358.         }
  359.         else    /* WILDCARD wild cards allowed */
  360.         {
  361.             if(wordmode)
  362.             {
  363.                 for(cs = (Uchar *)s->data,ls = s->length;ls--;cs++)
  364.                     if(!delim[*cs])
  365.                         break;
  366.                 if(!ls)
  367.                     return(0);    /* search string contains only delims, or is empty */
  368.                 if(r == BASE)
  369.                     return(0);
  370.                 if(!on_a_word(r,curbyt))    /* we can only succeed when on a word */
  371.                     return(0);
  372.                 ss = 0;    /* this is the current offset in the search string */
  373.                 tr = r;    /* this is a temporary rec_ptr for traversing the file */
  374.                 ts = s;    /* this is a temporary rec_ptr for traversing the search string */
  375.                 while(1)
  376.                 {
  377.                     if(!get_word_start(s,&ts,&ss,&ls,NULL))
  378.                         break;    /* we have a hit */
  379.                     if(!get_word_start(BASE,&tr,&curbyt,&lr,&offset))
  380.                         return(0);
  381.                     if(ls != lr)    /* word length mismatch */
  382.                         return(0);
  383.                     for(p = (Uchar *)ts->data + ss,q = (Uchar *)tr->data + curbyt,i = ls;i--;p++,q++)    /* compare the two words */
  384.                         if(*p != WILDCARD)
  385.                             if(*(t1 + *p) != *(t2 + *q))
  386.                                 return(0);
  387.                     curbyt += lr;    /* advance to past end of word in file */
  388.                     ss += ls;    /* advance to past end of word in search string */
  389.                 }
  390.             }
  391.             else
  392.                 do
  393.                 {
  394.                     if(r == BASE)
  395.                         return(0);
  396.                     if((ls = s->length) > lr)
  397.                         return(0);
  398.                     for(cs = (Uchar *)s->data;ls--;)
  399.                     {
  400.                         c1 = *cs++;
  401.                         c2 = *cr++;
  402.                         if(c1 != WILDCARD)
  403.                             if(*(t1 + c1) != *(t2 + c2))
  404.                                 return(0);
  405.                         offset++;
  406.                     }
  407.                     if((s = s->next) != (rec_ptr)&searchbuf->first) /* insure the file record ends here too */
  408.                     {
  409.                         if(cr != (Uchar *)&r->data[r->length])    /* search record ends, file record continues */
  410.                             return(0);
  411.                         r = r->next;
  412.                         lr = r->length;
  413.                         cr = (Uchar *)r->data;
  414.                         offset++;
  415.                     }
  416.                 } while(s != (rec_ptr)&searchbuf->first);
  417.         }
  418.     }
  419.     else    /* we are SET SEARCH END */
  420.     {
  421.         lr = curbyt;
  422.         if(regexp == 'r' && !wordmode)
  423.         {
  424.             if(endrec && (curbyt != r->length))    /* ignore attempts not at end of record when ...$ is present */
  425.                 return(0);
  426.             while(lr > 0)
  427.             {
  428.                 if((i = re_match(&pbuf,(const char *)(r->data + curbyt - lr),lr,0,NULL)) == -2)
  429.                     goto regex_error;
  430.                 else if(i >= 0)
  431.                 {
  432.                     if(lr == i)
  433.                     {
  434.                         if(startrec && (i != curbyt))    /* require match at beginning of record when ^... is present */
  435.                             return(0);
  436.                         return(-lr);
  437.                     }
  438.                 }
  439.                 lr--;
  440.             }
  441.             return(0);
  442.         }
  443.         s = searchbuf->last;
  444.         if(WINDOW[CURWINDOW].binary)    /* binary-mode search ignores linebreaks, has special handling for <0d> in search buffer */
  445.         {
  446.             if(!curbyt)    /* disallow bol matches in end mode */
  447.                 return(0);
  448.             ls = s->length;
  449.             cs = (Uchar *)s->data + ls;    /* start at the end of search buffer's last record */
  450.             while(1)
  451.             {
  452.                 if(r == BASE)    /* hit end of file */
  453.                     return(0);
  454. /* insure we have another search buffer byte */
  455.                 while(!ls)    /* hit beginning of this record in search buffer, advance */
  456.                 {
  457.                     if((s = s->prev) == (rec_ptr)&searchbuf->first)    /* hit beginning of search buffer, succeed */
  458.                         return(1);
  459.                     while(!lr)    /* insure another file byte is available */
  460.                     {
  461.                         if((r = r->prev) == BASE)
  462.                             return(0);
  463.                         lr = r->length;
  464.                         cr = (Uchar *)r->data + lr;
  465.                     }
  466.                     if(*(t2 + *--cr) != 13)    /* require a CR to match the search buffer linebreak */
  467.                         return(0);
  468.                     lr--;
  469.                     offset++;    /* advance for CR */
  470.                     ls = s->length;
  471.                     cs = (Uchar *)s->data + ls;    /* new pointers */
  472.                 }
  473. /* insure we have another file byte */
  474.                 while(!lr)    /* ran out on file record, advance */
  475.                 {
  476.                     if((r = r->prev) == BASE)
  477.                         return(0);
  478.                     lr = r->length;
  479.                     cr = (Uchar *)r->data + lr;
  480.                 }
  481.                 if(wild == 'n')
  482.                 {
  483.                     if(*(t1 + *--cs) != *(t2 + *--cr))    /* compare */
  484.                         return(0);
  485.                 }
  486.                 else
  487.                 {
  488.                     if(*--cs == WILDCARD)
  489.                         cr--;
  490.                     else
  491.                         if(*(t1 + *cs) != *(t2 + *--cr))    /* compare */
  492.                             return(0);
  493.                 }
  494.                 ls--;
  495.                 lr--;
  496.                 offset++;    /* advance offset */
  497.             }
  498.         }
  499.         if(wild == 'n' || regexp == 'r')    /* no wild cards, or in regex mode */
  500.         {
  501.             if(wordmode)
  502.             {
  503.                 if(regexp != 'r')
  504.                 {
  505.                     for(cs = (Uchar *)s->data,ls = s->length;ls--;cs++)
  506.                         if(!delim[*cs])
  507.                             break;
  508.                     if(!ls)
  509.                         return(0);    /* search string contains only delims, or is empty */
  510.                 }
  511.                 if(r == BASE)
  512.                     return(0);
  513.                 if(!on_a_wordend(r,curbyt))    /* we can only succeed when on a wordend */
  514.                     return(0);
  515.                 ss = strlen(s->data);    /* this is the current offset in the search string */
  516.                 tr = r;    /* this is a temporary rec_ptr for traversing the file */
  517.                 ts = s;    /* this is a temporary rec_ptr for traversing the search string */
  518.                 if(regexp == 'r')
  519.                 {
  520.                     if(!nwords)
  521.                         return(0);
  522.                     for(j = nwords - 1;j >= 0;j--)
  523.                     {
  524.                         if(startrecs[j] && curbyt)    /* ignore attempts not at beginning of record when ^... present */
  525.                             return(0);
  526.                         if(!get_word_end(BASE,&tr,&curbyt,&lr,&offset))
  527.                             return(0);
  528.                         if((i = re_match(wbuf + j,(const char *)tr->data + curbyt,lr,0,NULL)) == -2)
  529.                             goto regex_error;
  530.                         if(i < 0)
  531.                             return(0);
  532.                         if(endrecs[j] && (curbyt + i != r->length))    /* require match at end of record when ...$ present */
  533.                             return(0);
  534.                     }
  535.                 }
  536.                 else
  537.                 {
  538.                     while(1)
  539.                     {
  540.                         if(!get_word_end(s,&ts,&ss,&ls,NULL))
  541.                             break;    /* we have a hit */
  542.                         if(!get_word_end(BASE,&tr,&curbyt,&lr,&offset))
  543.                             return(0);
  544.                         if(ls != lr)    /* word length mismatch */
  545.                             return(0);
  546.                         for(p = (Uchar *)ts->data + ss,q = (Uchar *)tr->data + curbyt,i = ls;i--;p++,q++)    /* compare the two words */
  547.                             if(*(t1 + *p) != *(t2 + *q))
  548.                                 return(0);
  549.                     }
  550.                 }
  551.             }
  552.             else    /* not wordmode */
  553.                 do
  554.                 {
  555.                     if(r == BASE)
  556.                         return(0);
  557.                     if((ls = s->length) > lr)
  558.                         return(0);
  559.                     for(cs = (Uchar *)&s->data[ls];ls--;)
  560.                     {
  561.                         if(*(t1 + *--cs) != *(t2 + *--cr))
  562.                             return(0);
  563.                         offset--;
  564.                     }
  565.                     if((s = s->prev) != (rec_ptr)&searchbuf->first) /* insure the file record ends here too */
  566.                     {
  567.                         if(cr != (Uchar *)r->data)      /* search record ends, file record continues */
  568.                             return(0);
  569.                         r = r->prev;
  570.                         lr = r->length;
  571.                         cr = (Uchar *)&r->data[lr];
  572.                         offset--;
  573.                     }
  574.                 } while(s != (rec_ptr)&searchbuf->first);
  575.         }
  576.         else    /* WILDCARD wild cards allowed */
  577.         {
  578.             if(wordmode)
  579.             {
  580.                 for(cs = (Uchar *)s->data,ls = s->length;ls--;cs++)
  581.                     if(!delim[*cs])
  582.                         break;
  583.                 if(!ls)
  584.                     return(0);    /* search string contains only delims, or is empty */
  585.                 if(r == BASE)
  586.                     return(0);
  587.                 if(!on_a_wordend(r,curbyt))    /* we can only succeed when on a wordend */
  588.                     return(0);
  589.                 ss = strlen(s->data);    /* this is the current offset in the search string */
  590.                 tr = r;    /* this is a temporary rec_ptr for traversing the file */
  591.                 ts = s;    /* this is a temporary rec_ptr for traversing the search string */
  592.                 while(1)
  593.                 {
  594.                     if(!get_word_end(s,&ts,&ss,&ls,NULL))
  595.                         break;    /* we have a hit */
  596.                     if(!get_word_end(BASE,&tr,&curbyt,&lr,&offset))
  597.                         return(0);
  598.                     if(ls != lr)    /* word length mismatch */
  599.                         return(0);
  600.                     for(p = (Uchar *)ts->data + ss,q = (Uchar *)tr->data + curbyt,i = ls;i--;p++,q++)    /* compare the two words */
  601.                         if(*p != WILDCARD)
  602.                             if(*(t1 + *p) != *(t2 + *q))
  603.                                 return(0);
  604.                 }
  605.             }
  606.             else
  607.                 do
  608.                 {
  609.                     if(r == BASE)
  610.                         return(0);
  611.                     if((ls = s->length) > lr)
  612.                         return(0);
  613.                     for(cs = (Uchar *)&s->data[ls];ls--;)
  614.                     {
  615.                         c1 = *--cs;
  616.                         c2 = *--cr;
  617.                         if(c1 != WILDCARD)
  618.                             if(*(t1 + c1) != *(t2 + c2))
  619.                                 return(0);
  620.                         offset--;
  621.                     }
  622.                     if((s = s->prev) != (rec_ptr)&searchbuf->first) /* insure the file record ends here too */
  623.                     {
  624.                         if(cr != (Uchar *)r->data)      /* search record ends, file record continues */
  625.                             return(0);
  626.                         r = r->prev;
  627.                         lr = r->length;
  628.                         cr = (Uchar *)&r->data[lr];
  629.                         offset--;
  630.                     }
  631.                 } while(s != (rec_ptr)&searchbuf->first);
  632.         }
  633.     }
  634.     return(offset);
  635. regex_error:
  636.     strcpy(rbuf,"'");
  637.     memcpy(rbuf + 1,SEARCHBUF.first->data,SEARCHBUF.first->length);
  638.     strcpy(rbuf + SEARCHBUF.first->length + 1,"' is not a valid regular expression.");
  639.     slip_message(rbuf);
  640.     wait_message();
  641.     return(0);
  642. }
  643.  
  644. /******************************************************************************\
  645. |Routine: set_search_table
  646. |Callby: restore_par set_param
  647. |Purpose: Sets up a search table.
  648. |Arguments:
  649. |     file is the name of the search table, to be read in from disk file.
  650. \******************************************************************************/
  651. Int set_search_table(file)
  652. Char *file;
  653. {
  654.     FILE *fp;
  655.     Int l;
  656.     Uchar buf[512];
  657.     
  658.     strip_quotes(file);
  659.     envir_subs(file);
  660.     for(l = 0;l < 256;l++)
  661.         table[l] = l;
  662.     if(!(fp = fopen(file,"r")))
  663.         return(0);
  664.     while(fgets((Char *)buf,sizeof(buf),fp))
  665.         table[buf[0]] = buf[1];
  666.     fclose(fp);
  667.     return(1);
  668. }
  669.  
  670.